package com.wcy.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.wcy.constant.LoginConstant;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>Title:UserServiceDetailsServiceImpl.java</p >
 * <p>Description: </p >
 * <p>Copyright: 公共服务与应急管理战略业务本部 Copyright(c)2020</p >
 * <p>Date:2021/9/13 19:25</p >
 *
 * @author wcy (wangchaoyanga@mail.taiji.com.cn)
 * @version 1.0
 */
@Service
public class UserServiceDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        String login_type = requestAttributes.getRequest().getParameter("login_type");// 区分是后台人员还是用户登录
        if (StringUtils.isEmpty(login_type)) {
            throw new AuthenticationServiceException("登录类型不能为null");
        }
        if (LoginConstant.REFRESH_TOKEN.equals(requestAttributes.getRequest().getParameter("grant_type"))) {
            username = refreshTokenHandle(username, login_type);
        }
        switch (login_type) {
            case LoginConstant.ADMIN_TYPE:
                return loadSysUserByUsername(username);
            case LoginConstant.MEMBER_TYPE:
                return loadMemberUserByUsername(username);
            default:
                throw new AuthenticationServiceException("暂不支持的登录方式:" + login_type);
        }
    }

    private String refreshTokenHandle(String username, String login_type) {
        try {
            if (LoginConstant.ADMIN_TYPE.equals(login_type)) {
                return jdbcTemplate.queryForObject(LoginConstant.QUERY_ADMIN_USERNAME, String.class, username);
            } else if (LoginConstant.MEMBER_TYPE.equals(login_type)) {
                return jdbcTemplate.queryForObject(LoginConstant.QUERY_ADMIN_USERNAME, String.class, username);
            }
        } catch (DataAccessException e) {
            throw new UsernameNotFoundException("username not found");
        }
        return username;
    }

    /**
     * 会员的登录
     *
     * @param username
     * @return
     */
    private UserDetails loadMemberUserByUsername(String username) {
        User user = null;
        try {
            user = jdbcTemplate.queryForObject(LoginConstant.QUERY_MEMBER_SQL, new RowMapper<User>() {
                @Override
                public User mapRow(ResultSet resultSet, int i) throws SQLException {
                    long id = resultSet.getLong("id");
                    String password = resultSet.getString("password");
                    int status = resultSet.getInt("status");
                    return new User(String.valueOf(id), password, status == 1, true, true, true, Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER"))); // 使用userId代替username
                }
            }, username, username);
        } catch (DataAccessException e) {
            throw new UsernameNotFoundException("username not found");
        }
        return user;
    }

    /**
     * 后台管理人员的登录
     *
     * @param username
     * @return
     */
    private UserDetails loadSysUserByUsername(String username) {
        // 1 使用用户名查询用户
        // 2 查询这个用户对应的权限
        // 3 封装成一个UserDetails对象,返回
        User user = null;
        try {
            user = jdbcTemplate.queryForObject(LoginConstant.QUERY_ADMIN_SQL, new RowMapper<User>() {
                @Override
                public User mapRow(ResultSet resultSet, int i) throws SQLException {
                    long id = resultSet.getLong("id");
                    String password = resultSet.getString("password");
                    int status = resultSet.getInt("status");
                    return new User(String.valueOf(id), password, status == 1, true, true, true, getSysUserPermissions(id)); // 使用userId代替username
                }
            }, username);
        } catch (DataAccessException e) {
            throw new UsernameNotFoundException("username not found");
        }
        return user;
    }

    /**
     * 通过用户的id查询用户的权限数据
     *
     * @param id
     * @return
     */
    private Collection<? extends GrantedAuthority> getSysUserPermissions(long id) {
        List<String> strings = jdbcTemplate.queryForList(LoginConstant.QUERY_ROLE_CODE_ID_SQL, String.class, id);
        List<String> permissions = null;
        if (strings.contains(LoginConstant.ADMIN_ROLE_CODE)) {
            // 当用户为超级管理员时 拥有所有权限
            permissions = jdbcTemplate.queryForList(LoginConstant.QUERY_ALL_PERMISSIONS, String.class);
        } else {
            // 普通用户需要使用角色查询权限数据
            permissions = jdbcTemplate.queryForList(LoginConstant.QUERY_PERMISSION_SQL, String.class, id);
        }
        if (permissions.isEmpty()) {
            return Collections.emptySet();
        }
        return permissions.stream().distinct().map(SimpleGrantedAuthority::new).collect(Collectors.toSet());
    }

}


